"""
协程：执行效率比线程高，由程序自身控制，创建协程2种方式 asyncio 和 gevent 库；asyncio 更常用；
1.asyncio 是一个标准库，无需安装，采用async/await语法定义，适用于 I/O 密集型的网络编程，像网络爬虫、异步 HTTP 客户端等
2.gevent 是一个第三方协程库，借助 greenlet 实现协程。它使用猴子补丁（monkey patching）来修改标准库中的阻塞 I/O 函数，使它们变成非阻塞的，适用于处理大量并发连接的场景。

执行原理：两个协程可以在同一个线程中并发执行，事件循环会在它们之间切换，从而提高程序的效率。
（1）初始化阶段：
    开始事件循环：建两个协程 Coroutine1 和 Coroutine2，并将它们加入执行队列。
（2）执行 Coroutine1：
    从执行队列取出 Coroutine1 并开始执行。
    检查 Coroutine1 是否遇到阻塞。如果遇到阻塞，暂停 Coroutine1 并将其放回执行队列末尾，然后取出 Coroutine2 执行。
    如果没有遇到阻塞，Coroutine1 继续执行，直到执行完毕或者再次遇到阻塞。
（3）执行 Coroutine2：
    当 Coroutine1 暂停或者执行完毕后，从执行队列取出 Coroutine2 并开始执行。
    检查 Coroutine2 是否遇到阻塞。如果遇到阻塞，暂停 Coroutine2 并将其放回执行队列末尾，然后取出 Coroutine1 执行。
    如果没有遇到阻塞，Coroutine2 继续执行，直到执行完毕或者再次遇到阻塞。
（4）循环执行：
    不断重复上述步骤，直到执行队列为空。
（5）结束事件循环：
    当执行队列为空时，结束事件循环。
"""
# 1.async/await 适用于 I/O 密集型的网络编程，像网络爬虫、异步 HTTP 客户端等

import asyncio
import gevent

# 定义一个协程异步函数hello
async def hello():
    print("hello")
    task = asyncio.current_task()
    print(f"sleep前正在运行的协程的任务名: {task.get_name()}, 任务 ID: {id(task)}")
    await asyncio.sleep(1) # 模拟异步操作（函数内部可以使用 await 关键字来暂停协程的执行，等待异步操作完成）
    print(f"sleep后正在运行的协程的任务名: {task.get_name()}, 任务 ID: {id(task)}")
    print("Word!!")

# 场景一：定义主异步函数
async def main():

    # (1)创建1个协程对象（使用 asyncio.create_task 函数将协程函数 hello 封装成一个任务对象 task。）
    # task = asyncio.create_task(hello())
    # await task
    # (2)并发两个协程（asyncio.gather 会等待所有传入的协程都完成后才会继续执行）
    # await asyncio.gather(hello(),hello())
    # （3） 更多并发多个:列表表达式
    # await asyncio.gather(*[hello() for _ in range(5)])
    # （3-1）列表表达式展开写
    coroutines = [] #存储协程对象
    for _ in range(5):
        coroutine = hello()
        coroutines.append(coroutine)
    await asyncio.gather(*coroutines)
    # 等待协程完成


# 启动事件循环并运行 main 协程
asyncio.run(main())

"""
场景二：传参
"""

import asyncio


async def hello2(taskName, delay):
    print("hello")
    task = asyncio.current_task()
    print(f"sleep前正在运行的协程的任务名: {task.get_name()}, 任务 ID: {id(task)}")
    await asyncio.sleep(delay)
    print(f"sleep后正在运行的协程的任务名: {task.get_name()}, 任务 ID: {id(task)}")
    print("Word!!")


async def main2():
    coroutines = []
    for i in range(5):
        # 为每个协程传递不同的参数
        task_name = f"任务{i + 1}"
        delay_time = i + 1
        coroutine = hello2(task_name, delay_time)
        coroutines.append(coroutine)
    await asyncio.gather(*coroutines)


if __name__ == "__main__":
    asyncio.run(main2())




"""
定义协程函数：定义一个普通的函数 hello，在函数内部使用 gevent.sleep 函数来模拟异步操作。
创建协程对象：使用 gevent.spawn 函数将函数 hello 封装成一个协程对象 g。
等待协程完成：使用 g.join() 方法来等待协程执行完成。
"""
# 方式2：定义一个协程函数
def hello3():
    print("Hello")
    # 模拟异步操作
    gevent.sleep(1)
    print("World")

# 创建协程对象
# g = gevent.spawn(hello2)

# 等待协程完成
# g.join()

















